package com.hongliang.nio_c1.c1.bytebuffer;

import java.nio.ByteBuffer;

import static com.hongliang.nio_c1.utils.ByteBufferUtil.debugAll;

/**
 * @author Hongliang Zhu
 * @create 2021-08-22 12:09
 */
public class BufferExam {

    /**
     * 网络上有多条数据发送给服务端，数据之间使用 \n 进行分隔
     * 但由于某种原因这些数据在接收时，被进行了重新组合，例如原始数据有3条为
     * <p>
     * * Hello,world\n
     * * I’m zhangsan\n
     * * How are you?\n
     * <p>
     * 变成了下面的两个 byteBuffer (黏包，半包)
     * <p>
     * * Hello,world\nI’m zhangsan\nHo
     * * w are you?\n
     * <p>
     * 现在要求你编写程序，将错乱的数据恢复成原始的按 \n 分隔的数据
     *
     * @param args
     */
    public static void main(String[] args) {

        ByteBuffer source = ByteBuffer.allocate(32);
        //                     11            24
        source.put("Hello,world\nI'm zhangsan\nHo".getBytes());
//        split(source);
        split2(source);
        source.put("w are you?\nhaha!\n".getBytes());
//        split(source);

        split2(source);

    }

    private static void split(ByteBuffer source) {
        source.flip();
        for (int i = 0; i < source.limit(); i++) {
            if (source.get(i) == '\n') {
                int length = i + 1 - source.position();
                ByteBuffer buf = ByteBuffer.allocate(length);
                // 从source 读， 写到buf中
                for (int j = 0; j < length; j++) {
                    buf.put(source.get());
                }

                debugAll(buf);

            }
        }
        source.compact();

    }

    private static void split2(ByteBuffer source) {
        // 切换成读模式
        source.flip();
        // 当前读取限制
        int oldLimit = source.limit();
        for (int i = 0; i < oldLimit; i++) {
                if (source.get(i) == '\n') {
                    System.out.println(i);
                    ByteBuffer target = ByteBuffer.allocate(i + 1 - source.position());
                    // 设置目前读取的限制 0  ~ limit
                    source.limit(i+1);
                    // 从source读取到target
                    target.put(source);
                    debugAll(target);

                    // 设置回来原来的limit，进行下一次的读取
                    source.limit(oldLimit);
                }

        }
        source.compact();

    }

}
